using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class FSM<ST, EV>
{
    Dictionary<ST, Dictionary<EV, ST>> Fsm = new Dictionary<ST, Dictionary<EV, ST>>();

    Dictionary<ST, List<FSMBehaviour>> StatesRelation = new Dictionary<ST, List<FSMBehaviour>>();
    ST StartingState;
    public ST CurrentState;

    public FSM(ST startingState)
    {
        StartingState = startingState;
        Reset();
    }
    public void Reset()
    {
        SetState(StartingState);
    }
    public ST GetState()
    {
        return CurrentState;
    }
    public void SetRelation(ST origin, EV eventParam, ST destiny)
    {
        if (!Fsm.ContainsKey(origin))
        {
            Fsm[origin] = new Dictionary<EV, ST>();
        }
        Fsm[origin][eventParam] = destiny;
    }
    public void AssignBehaviour(ST state, FSMBehaviour behaviour)
    {
        if (!StatesRelation.ContainsKey(state))
        {
            StatesRelation[state] = new List<FSMBehaviour>();
        }
        StatesRelation[state].Add(behaviour);
    }
    public void SendEvent(EV eventParam)
    {
        if (Fsm.ContainsKey(CurrentState))
        {
            if (Fsm[CurrentState].ContainsKey(eventParam))
            {
                SetState(Fsm[CurrentState][eventParam]);
            }
        }
    }
    private void SetState(ST destinyState)
    {
        //Desactivo todos los behaviours del estado anterior.
        if (StatesRelation.ContainsKey(CurrentState))
        {
            foreach (FSMBehaviour fb in StatesRelation[CurrentState])
            {
                if(fb.IsEnabled())
                fb.Disable();
            }
        }
        //cambio de estado
        CurrentState = destinyState;

        //activo todos los behaviours del nuevo estado.
        if (StatesRelation.ContainsKey(CurrentState))
        {
            foreach (FSMBehaviour fb in StatesRelation[CurrentState])
            {
                if(fb.IsEnabled() == false)
                fb.Enable();
            }
        }
    }
    public void Update()
    {
        if (StatesRelation.ContainsKey(CurrentState) == false) return;

        foreach (FSMBehaviour fb in StatesRelation[CurrentState])
        {
            if (fb.IsEnabled())
            {
                fb.Update();
            }
        }
    }
}
